package br.com.poc.pitagorasnumero.model.bo.impl;

import java.text.Normalizer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

import br.com.poc.pitagorasnumero.type.TablePitagoricaType;
import br.com.poc.pitagorasnumero.util.StringUtil;

/**
 * The Class TabelaPitagorasManager.
 * 
 * @author irlan.gomes
 */
class CalculationNumberManager {

	/** The Constant REMOVE_ACENTS_PATTERN. */
	private static final String REMOVE_ACENTS_PATTERN = "\\p{InCombiningDiacriticalMarks}+";

	/**
	 * Validate name.
	 * 
	 * @param name
	 *            the name
	 * @return the name validated
	 */
	protected String validateName(final String name) {

		final String nameLower = name.toUpperCase(Locale.US);

		final String accentRemovedName = removeAccent(nameLower);

		return accentRemovedName;
	}

	/**
	 * Reduces to a single number the letters of the name.
	 * 
	 * @param nameOrLetters
	 *            can enter the name or letters
	 * @return numerical value of the name
	 */
	protected int calculateLetters(final String[] nameOrLetters) {

		final List<TablePitagoricaType> parseLetter = convertLetterNumber(nameOrLetters);

		final int sumLetter = this.sumLetter(parseLetter);

		final int numberMagic = this.reduceNumberMagic(sumLetter);

		return numberMagic;
	}

	/**
	 * Converter letter in number.
	 * 
	 * @param letters
	 *            the letter
	 * @return the list of TablePitagoricaDomain
	 */
	protected List<TablePitagoricaType> convertLetterNumber(
			final String[] letters) {

		final List<TablePitagoricaType> tablePitagList = new ArrayList<TablePitagoricaType>();

		for (int i = 0; i < letters.length; i++) {

			if (StringUtil.notEmpty(letters[i])) {

				final String letterItem = String.valueOf(letters[i]);

				final TablePitagoricaType valueLetter = TablePitagoricaType
						.getValueLetter(letterItem);

				tablePitagList.add(valueLetter);
			}
		}

		return tablePitagList;
	}

	/**
	 * Remove accents.
	 * 
	 * @param value
	 *            the value
	 * @return the name without accents.
	 */
	private String removeAccent(final String value) {

		final String nfdNormalized = Normalizer.normalize(value,
				Normalizer.Form.NFD);

		final Pattern pattern = Pattern.compile(REMOVE_ACENTS_PATTERN);

		return pattern.matcher(nfdNormalized).replaceAll("");
	}

	/**
	 * Sum letter.
	 * 
	 * @param tablePitagorica
	 *            the convert letter in number
	 * @return the return value added
	 */
	protected int sumLetter(final List<TablePitagoricaType> tablePitagorica) {

		int result = 0;

		for (final TablePitagoricaType table : tablePitagorica) {
			result += table.getValueLetter();
		}

		return result;
	}

	/**
	 * Reduce number magic.
	 * 
	 * @param sumLetter
	 *            letter the sum letter
	 * @return the int
	 */
	protected int reduceNumberMagic(Integer sumLetter) {

		if (sumLetter > 9 && sumLetter != 11 && sumLetter != 22) {

			sumLetter = this.decomposeNumber(sumLetter);
			sumLetter = this.reduceNumberMagic(sumLetter);
		}

		return sumLetter;
	}

	/**
	 * Decompose number.
	 * 
	 * @param sumLetter
	 *            the sum letter
	 * @return the integer
	 */
	private Integer decomposeNumber(Integer sumLetter) {

		final String convertString = String.valueOf(sumLetter);
		int itemOne = 0, itemTwo = 0, itemThree = 0;

		if (sumLetter <= 99) {
			itemOne = Character.getNumericValue(convertString.charAt(0));
			itemTwo = Character.getNumericValue(convertString.charAt(1));
		} else {
			// for more than 100 numbers
			itemOne = Character.getNumericValue(convertString.charAt(0));
			itemTwo = Character.getNumericValue(convertString.charAt(1));
			itemThree = Character.getNumericValue(convertString.charAt(2));
		}

		sumLetter = itemOne + itemTwo + itemThree;
		return sumLetter;
	}
}
